From 5c74609870471f83fc12ddf799322975396dc0a7 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Tue, 8 Feb 2005 19:57:24 +0000 Subject: [PATCH] bitkeeper revision 1.1159.256.1 (420919a4fFt2x7Ej4o_xqAI2CSYN8Q) mmu_update fixes for x86_64. About halfway there. Signed-off-by: keir.fraser@cl.cam.ac.uk --- xen/arch/x86/boot/x86_64.S | 10 +- xen/arch/x86/mm.c | 242 +++++++++++++++++++++++++----- xen/include/asm-x86/cpufeature.h | 2 + xen/include/asm-x86/page.h | 90 +++++------ xen/include/asm-x86/x86_32/page.h | 29 +++- xen/include/asm-x86/x86_64/page.h | 49 +++--- 6 files changed, 307 insertions(+), 115 deletions(-) diff --git a/xen/arch/x86/boot/x86_64.S b/xen/arch/x86/boot/x86_64.S index 9d61523138..2b89d9caa4 100644 --- a/xen/arch/x86/boot/x86_64.S +++ b/xen/arch/x86/boot/x86_64.S @@ -75,6 +75,7 @@ __start: cpuid bt $29,%edx # Long mode feature? jnc bad_cpu + mov %edx,%edi skip_boot_checks: /* Set up FPU. */ @@ -91,9 +92,12 @@ skip_boot_checks: /* Set up EFER (Extended Feature Enable Register). */ movl $MSR_EFER, %ecx rdmsr - /* Long Mode, SYSCALL/SYSRET, No-Execute */ - movl $(EFER_LME|EFER_SCE|EFER_NX),%eax - wrmsr + btsl $_EFER_LME,%eax /* Long Mode */ + btsl $_EFER_SCE,%eax /* SYSCALL/SYSRET */ + btl $20,%edi /* CPUID 0x80000001, EDX[20] */ + jnc 1f + btsl $_EFER_NX,%eax /* No-Execute */ +1: wrmsr mov $0x80050033,%eax /* hi-to-lo: PG,AM,WP,NE,ET,MP,PE */ mov %eax,%cr0 diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 1c030ffd1a..6ae4d0e95c 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -335,47 +335,48 @@ static int get_page_and_type_from_pagenr(unsigned long page_nr, /* - * We allow an L2 tables to map each other (a.k.a. linear page tables). It - * needs some special care with reference counst and access permissions: + * We allow root tables to map each other (a.k.a. linear page tables). It + * needs some special care with reference counts and access permissions: * 1. The mapping entry must be read-only, or the guest may get write access * to its own PTEs. * 2. We must only bump the reference counts for an *already validated* * L2 table, or we can end up in a deadlock in get_page_type() by waiting * on a validation that is required to complete that validation. * 3. We only need to increment the reference counts for the mapped page - * frame if it is mapped by a different L2 table. This is sufficient and - * also necessary to allow validation of an L2 table mapping itself. + * frame if it is mapped by a different root table. This is sufficient and + * also necessary to allow validation of a root table mapping itself. */ static int get_linear_pagetable( - l2_pgentry_t l2e, unsigned long pfn, struct domain *d) + root_pgentry_t re, unsigned long re_pfn, struct domain *d) { u32 x, y; struct pfn_info *page; + unsigned long pfn; - if ( (l2_pgentry_val(l2e) & _PAGE_RW) ) + if ( (root_pgentry_val(re) & _PAGE_RW) ) { MEM_LOG("Attempt to create linear p.t. with write perms"); return 0; } - if ( (l2_pgentry_val(l2e) >> PAGE_SHIFT) != pfn ) + if ( (pfn = root_pgentry_to_pfn(re)) != re_pfn ) { /* Make sure the mapped frame belongs to the correct domain. */ - if ( unlikely(!get_page_from_pagenr(l2_pgentry_to_pfn(l2e), d)) ) + if ( unlikely(!get_page_from_pagenr(pfn, d)) ) return 0; /* * Make sure that the mapped frame is an already-validated L2 table. * If so, atomically increment the count (checking for overflow). */ - page = &frame_table[l2_pgentry_to_pfn(l2e)]; + page = &frame_table[pfn]; y = page->u.inuse.type_info; do { x = y; if ( unlikely((x & PGT_count_mask) == PGT_count_mask) || unlikely((x & (PGT_type_mask|PGT_validated)) != - (PGT_l2_page_table|PGT_validated)) ) + (PGT_root_page_table|PGT_validated)) ) { put_page(page); return 0; @@ -400,9 +401,9 @@ get_page_from_l1e( if ( !(l1v & _PAGE_PRESENT) ) return 1; - if ( unlikely(l1v & (_PAGE_GLOBAL|_PAGE_PAT)) ) + if ( unlikely(l1v & L1_DISALLOW_MASK) ) { - MEM_LOG("Bad L1 type settings %04lx", l1v & (_PAGE_GLOBAL|_PAGE_PAT)); + MEM_LOG("Bad L1 type settings %04lx", l1v & L1_DISALLOW_MASK); return 0; } @@ -439,10 +440,10 @@ get_page_from_l2e( if ( !(l2_pgentry_val(l2e) & _PAGE_PRESENT) ) return 1; - if ( unlikely((l2_pgentry_val(l2e) & (_PAGE_GLOBAL|_PAGE_PSE))) ) + if ( unlikely((l2_pgentry_val(l2e) & L2_DISALLOW_MASK)) ) { MEM_LOG("Bad L2 page type settings %04lx", - l2_pgentry_val(l2e) & (_PAGE_GLOBAL|_PAGE_PSE)); + l2_pgentry_val(l2e) & L2_DISALLOW_MASK); return 0; } @@ -450,12 +451,62 @@ get_page_from_l2e( l2_pgentry_to_pfn(l2e), PGT_l1_page_table | (va_idx<> PAGE_SHIFT) != pfn) ) + put_page_and_type(&frame_table[l3_pgentry_to_pfn(l3e)]); +} + + +static void put_page_from_l4e(l4_pgentry_t l4e, unsigned long pfn) +{ + if ( (l4_pgentry_val(l4e) & _PAGE_PRESENT) && + ((l4_pgentry_val(l4e) >> PAGE_SHIFT) != pfn) ) + put_page_and_type(&frame_table[l4_pgentry_to_pfn(l4e)]); +} + +#endif /* __x86_64__ */ + + +static int alloc_l1_table(struct pfn_info *page) +{ + struct domain *d = page_get_owner(page); + unsigned long pfn = page_to_pfn(page); + l1_pgentry_t *pl1e; + int i; + + pl1e = map_domain_mem(pfn << PAGE_SHIFT); + + for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ ) + if ( unlikely(!get_page_from_l1e(pl1e[i], d)) ) + goto fail; + + unmap_domain_mem(pl1e); + return 1; + + fail: + while ( i-- > 0 ) + put_page_from_l1e(pl1e[i], d); + + unmap_domain_mem(pl1e); + return 0; +} + + static int alloc_l2_table(struct pfn_info *page) { struct domain *d = page_get_owner(page); - unsigned long page_nr = page_to_pfn(page); + unsigned long pfn = page_to_pfn(page); l2_pgentry_t *pl2e; int i; - pl2e = map_domain_mem(page_nr << PAGE_SHIFT); + pl2e = map_domain_mem(pfn << PAGE_SHIFT); for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ ) - if ( unlikely(!get_page_from_l2e(pl2e[i], page_nr, d, i)) ) + if ( unlikely(!get_page_from_l2e(pl2e[i], pfn, d, i)) ) goto fail; #if defined(__i386__) @@ -533,7 +629,7 @@ static int alloc_l2_table(struct pfn_info *page) &idle_pg_table[DOMAIN_ENTRIES_PER_L2_PAGETABLE], HYPERVISOR_ENTRIES_PER_L2_PAGETABLE * sizeof(l2_pgentry_t)); pl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] = - mk_l2_pgentry((page_nr << PAGE_SHIFT) | __PAGE_HYPERVISOR); + mk_l2_pgentry((pfn << PAGE_SHIFT) | __PAGE_HYPERVISOR); pl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] = mk_l2_pgentry(__pa(page_get_owner(page)->arch.mm_perdomain_pt) | __PAGE_HYPERVISOR); @@ -544,61 +640,67 @@ static int alloc_l2_table(struct pfn_info *page) fail: while ( i-- > 0 ) - put_page_from_l2e(pl2e[i], page_nr); + put_page_from_l2e(pl2e[i], pfn); unmap_domain_mem(pl2e); return 0; } -static int alloc_l1_table(struct pfn_info *page) +#ifdef __x86_64__ + +static int alloc_l3_table(struct pfn_info *page) { struct domain *d = page_get_owner(page); - unsigned long page_nr = page_to_pfn(page); - l1_pgentry_t *pl1e; + unsigned long pfn = page_to_pfn(page); + l3_pgentry_t *pl3e = page_to_virt(page); int i; - pl1e = map_domain_mem(page_nr << PAGE_SHIFT); - - for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ ) - if ( unlikely(!get_page_from_l1e(pl1e[i], d)) ) + for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ ) + if ( unlikely(!get_page_from_l3e(pl3e[i], pfn, d)) ) goto fail; - unmap_domain_mem(pl1e); return 1; fail: while ( i-- > 0 ) - put_page_from_l1e(pl1e[i], d); + put_page_from_l3e(pl3e[i], pfn); - unmap_domain_mem(pl1e); return 0; } -static void free_l2_table(struct pfn_info *page) +static int alloc_l4_table(struct pfn_info *page) { - unsigned long page_nr = page - frame_table; - l2_pgentry_t *pl2e; - int i; + struct domain *d = page_get_owner(page); + unsigned long pfn = page_to_pfn(page); + l4_pgentry_t *pl4e = page_to_virt(page); + int i; - pl2e = map_domain_mem(page_nr << PAGE_SHIFT); + for ( i = 0; i < L4_PAGETABLE_ENTRIES; i++ ) + if ( unlikely(!get_page_from_l4e(pl4e[i], pfn, d)) ) + goto fail; - for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ ) - put_page_from_l2e(pl2e[i], page_nr); + return 1; - unmap_domain_mem(pl2e); + fail: + while ( i-- > 0 ) + put_page_from_l4e(pl4e[i], pfn); + + return 0; } +#endif /* __x86_64__ */ + static void free_l1_table(struct pfn_info *page) { struct domain *d = page_get_owner(page); - unsigned long page_nr = page - frame_table; + unsigned long pfn = page_to_pfn(page); l1_pgentry_t *pl1e; int i; - pl1e = map_domain_mem(page_nr << PAGE_SHIFT); + pl1e = map_domain_mem(pfn << PAGE_SHIFT); for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ ) put_page_from_l1e(pl1e[i], d); @@ -607,6 +709,47 @@ static void free_l1_table(struct pfn_info *page) } +static void free_l2_table(struct pfn_info *page) +{ + unsigned long pfn = page_to_pfn(page); + l2_pgentry_t *pl2e; + int i; + + pl2e = map_domain_mem(pfn << PAGE_SHIFT); + + for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ ) + put_page_from_l2e(pl2e[i], pfn); + + unmap_domain_mem(pl2e); +} + + +#ifdef __x86_64__ + +static void free_l3_table(struct pfn_info *page) +{ + unsigned long pfn = page_to_pfn(page); + l3_pgentry_t *pl3e = page_to_virt(page); + int i; + + for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ ) + put_page_from_l3e(pl3e[i], pfn); +} + + +static void free_l4_table(struct pfn_info *page) +{ + unsigned long pfn = page_to_pfn(page); + l4_pgentry_t *pl4e = page_to_virt(page); + int i; + + for ( i = 0; i < L4_PAGETABLE_ENTRIES; i++ ) + put_page_from_l4e(pl4e[i], pfn); +} + +#endif /* __x86_64__ */ + + static inline int update_l2e(l2_pgentry_t *pl2e, l2_pgentry_t ol2e, l2_pgentry_t nl2e) @@ -738,6 +881,12 @@ int alloc_page_type(struct pfn_info *page, unsigned int type) return alloc_l1_table(page); case PGT_l2_page_table: return alloc_l2_table(page); +#ifdef __x86_64__ + case PGT_l3_page_table: + return alloc_l3_table(page); + case PGT_l4_page_table: + return alloc_l4_table(page); +#endif case PGT_gdt_page: case PGT_ldt_page: return alloc_segdesc_page(page); @@ -766,6 +915,16 @@ void free_page_type(struct pfn_info *page, unsigned int type) free_l2_table(page); break; +#ifdef __x86_64__ + case PGT_l3_page_table: + free_l3_table(page); + break; + + case PGT_l4_page_table: + free_l4_table(page); + break; +#endif + default: BUG(); } @@ -856,7 +1015,8 @@ int get_page_type(struct pfn_info *page, u32 type) * circumstances should be very rare. */ struct domain *d = page_get_owner(page); - if ( unlikely(NEED_FLUSH(tlbflush_time[d->exec_domain[0]->processor], + if ( unlikely(NEED_FLUSH(tlbflush_time[d->exec_domain[0]-> + processor], page->tlbflush_timestamp)) ) { perfc_incr(need_flush_tlb_flush); diff --git a/xen/include/asm-x86/cpufeature.h b/xen/include/asm-x86/cpufeature.h index 117ca6a9d7..58aae2a74e 100644 --- a/xen/include/asm-x86/cpufeature.h +++ b/xen/include/asm-x86/cpufeature.h @@ -48,6 +48,7 @@ /* Don't duplicate feature flags which are redundant with Intel! */ #define X86_FEATURE_SYSCALL (1*32+11) /* SYSCALL/SYSRET */ #define X86_FEATURE_MP (1*32+19) /* MP Capable. */ +#define X86_FEATURE_NX (1*32+20) /* No-Execute Bit. */ #define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */ #define X86_FEATURE_LM (1*32+29) /* Long Mode (x86-64) */ #define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */ @@ -98,6 +99,7 @@ #define cpu_has_xmm boot_cpu_has(X86_FEATURE_XMM) #define cpu_has_ht boot_cpu_has(X86_FEATURE_HT) #define cpu_has_mp boot_cpu_has(X86_FEATURE_MP) +#define cpu_has_nx boot_cpu_has(X86_FEATURE_NX) #define cpu_has_k6_mtrr boot_cpu_has(X86_FEATURE_K6_MTRR) #define cpu_has_cyrix_arr boot_cpu_has(X86_FEATURE_CYRIX_ARR) #define cpu_has_centaur_mcr boot_cpu_has(X86_FEATURE_CENTAUR_MCR) diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h index 93801084f6..9b3c55fb11 100644 --- a/xen/include/asm-x86/page.h +++ b/xen/include/asm-x86/page.h @@ -12,37 +12,37 @@ /* Page-table type. */ #ifndef __ASSEMBLY__ typedef struct { unsigned long pt_lo; } pagetable_t; -#define pagetable_val(_x) ((_x).pt_lo) -#define mk_pagetable(_x) ( (pagetable_t) { (_x) } ) +#define pagetable_val(_x) ((_x).pt_lo) +#define mk_pagetable(_x) ( (pagetable_t) { (_x) } ) #endif #ifndef __ASSEMBLY__ -#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_SIZE (1UL << PAGE_SHIFT) #else -#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_SIZE (1 << PAGE_SHIFT) #endif -#define PAGE_MASK (~(PAGE_SIZE-1)) +#define PAGE_MASK (~(PAGE_SIZE-1)) -#define clear_page(_p) memset((void *)(_p), 0, PAGE_SIZE) -#define copy_page(_t,_f) memcpy((void *)(_t), (void *)(_f), PAGE_SIZE) +#define clear_page(_p) memset((void *)(_p), 0, PAGE_SIZE) +#define copy_page(_t,_f) memcpy((void *)(_t), (void *)(_f), PAGE_SIZE) -#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET) -#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) -#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) -#define pfn_to_page(_pfn) (frame_table + (_pfn)) -#define phys_to_page(kaddr) (frame_table + ((kaddr) >> PAGE_SHIFT)) -#define virt_to_page(kaddr) (frame_table + (__pa(kaddr) >> PAGE_SHIFT)) -#define VALID_PAGE(page) ((page - frame_table) < max_mapnr) +#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET) +#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) +#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) +#define pfn_to_page(_pfn) (frame_table + (_pfn)) +#define phys_to_page(kaddr) (frame_table + ((kaddr) >> PAGE_SHIFT)) +#define virt_to_page(kaddr) (frame_table + (__pa(kaddr) >> PAGE_SHIFT)) +#define VALID_PAGE(page) ((page - frame_table) < max_mapnr) /* * NB. We don't currently track I/O holes in the physical RAM space. * For now we guess that I/O devices will be mapped in the first 1MB * (e.g., VGA buffers) or beyond the end of physical RAM. */ -#define pfn_is_ram(_pfn) (((_pfn) > 0x100) && ((_pfn) < max_page)) +#define pfn_is_ram(_pfn) (((_pfn) > 0x100) && ((_pfn) < max_page)) /* High table entries are reserved by the hypervisor. */ -#define DOMAIN_ENTRIES_PER_L2_PAGETABLE \ +#define DOMAIN_ENTRIES_PER_L2_PAGETABLE \ (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) #define HYPERVISOR_ENTRIES_PER_L2_PAGETABLE \ (L2_PAGETABLE_ENTRIES - DOMAIN_ENTRIES_PER_L2_PAGETABLE) @@ -65,48 +65,48 @@ extern void paging_init(void); /* Flush global pages as well. */ #define __pge_off() \ - do { \ - __asm__ __volatile__( \ - "mov %0, %%cr4; # turn off PGE " \ - :: "r" (mmu_cr4_features & ~X86_CR4_PGE)); \ - } while (0) + do { \ + __asm__ __volatile__( \ + "mov %0, %%cr4; # turn off PGE " \ + : : "r" (mmu_cr4_features & ~X86_CR4_PGE) ); \ + } while ( 0 ) #define __pge_on() \ - do { \ - __asm__ __volatile__( \ - "mov %0, %%cr4; # turn off PGE " \ - :: "r" (mmu_cr4_features)); \ - } while (0) + do { \ + __asm__ __volatile__( \ + "mov %0, %%cr4; # turn off PGE " \ + : : "r" (mmu_cr4_features) ); \ + } while ( 0 ) -#define __flush_tlb_pge() \ - do { \ - __pge_off(); \ - __flush_tlb(); \ - __pge_on(); \ - } while (0) +#define __flush_tlb_pge() \ + do { \ + __pge_off(); \ + __flush_tlb(); \ + __pge_on(); \ + } while ( 0 ) #define __flush_tlb_one(__addr) \ -__asm__ __volatile__("invlpg %0": :"m" (*(char *) (__addr))) + __asm__ __volatile__("invlpg %0": :"m" (*(char *) (__addr))) #endif /* !__ASSEMBLY__ */ -#define _PAGE_PRESENT 0x001 -#define _PAGE_RW 0x002 -#define _PAGE_USER 0x004 -#define _PAGE_PWT 0x008 -#define _PAGE_PCD 0x010 -#define _PAGE_ACCESSED 0x020 -#define _PAGE_DIRTY 0x040 -#define _PAGE_PAT 0x080 -#define _PAGE_PSE 0x080 -#define _PAGE_GLOBAL 0x100 +#define _PAGE_PRESENT 0x001UL +#define _PAGE_RW 0x002UL +#define _PAGE_USER 0x004UL +#define _PAGE_PWT 0x008UL +#define _PAGE_PCD 0x010UL +#define _PAGE_ACCESSED 0x020UL +#define _PAGE_DIRTY 0x040UL +#define _PAGE_PAT 0x080UL +#define _PAGE_PSE 0x080UL +#define _PAGE_GLOBAL 0x100UL #define __PAGE_HYPERVISOR \ - (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) + (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) #define __PAGE_HYPERVISOR_NOCACHE \ - (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_PCD | _PAGE_ACCESSED) + (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_PCD | _PAGE_ACCESSED) #define MAKE_GLOBAL(_x) ((_x) | _PAGE_GLOBAL) diff --git a/xen/include/asm-x86/x86_32/page.h b/xen/include/asm-x86/x86_32/page.h index 9b5efe82b8..277888d7ac 100644 --- a/xen/include/asm-x86/x86_32/page.h +++ b/xen/include/asm-x86/x86_32/page.h @@ -27,20 +27,24 @@ typedef l2_pgentry_t root_pgentry_t; #endif /* !__ASSEMBLY__ */ /* Strip type from a table entry. */ -#define l1_pgentry_val(_x) ((_x).l1_lo) -#define l2_pgentry_val(_x) ((_x).l2_lo) +#define l1_pgentry_val(_x) ((_x).l1_lo) +#define l2_pgentry_val(_x) ((_x).l2_lo) +#define root_pgentry_val(_x) (l2_pgentry_val(_x)) /* Add type to a table entry. */ -#define mk_l1_pgentry(_x) ( (l1_pgentry_t) { (_x) } ) -#define mk_l2_pgentry(_x) ( (l2_pgentry_t) { (_x) } ) +#define mk_l1_pgentry(_x) ( (l1_pgentry_t) { (_x) } ) +#define mk_l2_pgentry(_x) ( (l2_pgentry_t) { (_x) } ) +#define mk_root_pgentry(_x) (mk_l2_pgentry(_x)) /* Turn a typed table entry into a physical address. */ -#define l1_pgentry_to_phys(_x) (l1_pgentry_val(_x) & PAGE_MASK) -#define l2_pgentry_to_phys(_x) (l2_pgentry_val(_x) & PAGE_MASK) +#define l1_pgentry_to_phys(_x) (l1_pgentry_val(_x) & PAGE_MASK) +#define l2_pgentry_to_phys(_x) (l2_pgentry_val(_x) & PAGE_MASK) +#define root_pgentry_to_phys(_x) (l2_pgentry_to_phys(_x)) /* Turn a typed table entry into a page index. */ -#define l1_pgentry_to_pfn(_x) (l1_pgentry_val(_x) >> PAGE_SHIFT) -#define l2_pgentry_to_pfn(_x) (l2_pgentry_val(_x) >> PAGE_SHIFT) +#define l1_pgentry_to_pfn(_x) (l1_pgentry_val(_x) >> PAGE_SHIFT) +#define l2_pgentry_to_pfn(_x) (l2_pgentry_val(_x) >> PAGE_SHIFT) +#define root_pgentry_to_pfn(_x) (l2_pgentry_to_pfn(_x)) /* Pagetable walking. */ #define l2_pgentry_to_l1(_x) \ @@ -55,4 +59,13 @@ typedef l2_pgentry_t root_pgentry_t; /* Given a virtual address, get an entry offset into a linear page table. */ #define l1_linear_offset(_a) ((_a) >> PAGE_SHIFT) +#define PGT_root_page_table PGT_l2_page_table + +#define _PAGE_NX 0UL + +#define L1_DISALLOW_MASK (3UL << 7) +#define L2_DISALLOW_MASK (7UL << 7) +#define L3_DISALLOW_MASK (7UL << 7) +#define L2_DISALLOW_MASK (7UL << 7) + #endif /* __X86_32_PAGE_H__ */ diff --git a/xen/include/asm-x86/x86_64/page.h b/xen/include/asm-x86/x86_64/page.h index 318df434fc..96bdb540f1 100644 --- a/xen/include/asm-x86/x86_64/page.h +++ b/xen/include/asm-x86/x86_64/page.h @@ -18,8 +18,8 @@ #define __PAGE_OFFSET (0xFFFF830000000000) -/* These may increase in future (phys. bits in particular). */ -#define PADDR_BITS 40 +/* These are page-table limitations. Current CPUs support only 40-bit phys. */ +#define PADDR_BITS 52 #define VADDR_BITS 48 #define PADDR_MASK ((1UL << PADDR_BITS)-1) #define VADDR_MASK ((1UL << VADDR_BITS)-1) @@ -34,28 +34,32 @@ typedef l4_pgentry_t root_pgentry_t; #endif /* !__ASSEMBLY__ */ /* Strip type from a table entry. */ -#define l1_pgentry_val(_x) ((_x).l1_lo) -#define l2_pgentry_val(_x) ((_x).l2_lo) -#define l3_pgentry_val(_x) ((_x).l3_lo) -#define l4_pgentry_val(_x) ((_x).l4_lo) +#define l1_pgentry_val(_x) ((_x).l1_lo) +#define l2_pgentry_val(_x) ((_x).l2_lo) +#define l3_pgentry_val(_x) ((_x).l3_lo) +#define l4_pgentry_val(_x) ((_x).l4_lo) +#define root_pgentry_val(_x) (l4_pgentry_val(_x)) /* Add type to a table entry. */ -#define mk_l1_pgentry(_x) ( (l1_pgentry_t) { (_x) } ) -#define mk_l2_pgentry(_x) ( (l2_pgentry_t) { (_x) } ) -#define mk_l3_pgentry(_x) ( (l3_pgentry_t) { (_x) } ) -#define mk_l4_pgentry(_x) ( (l4_pgentry_t) { (_x) } ) +#define mk_l1_pgentry(_x) ( (l1_pgentry_t) { (_x) } ) +#define mk_l2_pgentry(_x) ( (l2_pgentry_t) { (_x) } ) +#define mk_l3_pgentry(_x) ( (l3_pgentry_t) { (_x) } ) +#define mk_l4_pgentry(_x) ( (l4_pgentry_t) { (_x) } ) +#define mk_root_pgentry(_x) (mk_l4_pgentry(_x)) /* Turn a typed table entry into a physical address. */ -#define l1_pgentry_to_phys(_x) (l1_pgentry_val(_x) & (PADDR_MASK & PAGE_MASK)) -#define l2_pgentry_to_phys(_x) (l2_pgentry_val(_x) & (PADDR_MASK & PAGE_MASK)) -#define l3_pgentry_to_phys(_x) (l3_pgentry_val(_x) & (PADDR_MASK & PAGE_MASK)) -#define l4_pgentry_to_phys(_x) (l4_pgentry_val(_x) & (PADDR_MASK & PAGE_MASK)) +#define l1_pgentry_to_phys(_x) (l1_pgentry_val(_x) & (PADDR_MASK&PAGE_MASK)) +#define l2_pgentry_to_phys(_x) (l2_pgentry_val(_x) & (PADDR_MASK&PAGE_MASK)) +#define l3_pgentry_to_phys(_x) (l3_pgentry_val(_x) & (PADDR_MASK&PAGE_MASK)) +#define l4_pgentry_to_phys(_x) (l4_pgentry_val(_x) & (PADDR_MASK&PAGE_MASK)) +#define root_pgentry_to_phys(_x) (l4_pgentry_to_phys(_x)) /* Turn a typed table entry into a page index. */ -#define l1_pgentry_to_pfn(_x) (l1_pgentry_val(_x) >> PAGE_SHIFT) -#define l2_pgentry_to_pfn(_x) (l2_pgentry_val(_x) >> PAGE_SHIFT) -#define l3_pgentry_to_pfn(_x) (l3_pgentry_val(_x) >> PAGE_SHIFT) -#define l4_pgentry_to_pfn(_x) (l4_pgentry_val(_x) >> PAGE_SHIFT) +#define l1_pgentry_to_pfn(_x) (l1_pgentry_val(_x) >> PAGE_SHIFT) +#define l2_pgentry_to_pfn(_x) (l2_pgentry_val(_x) >> PAGE_SHIFT) +#define l3_pgentry_to_pfn(_x) (l3_pgentry_val(_x) >> PAGE_SHIFT) +#define l4_pgentry_to_pfn(_x) (l4_pgentry_val(_x) >> PAGE_SHIFT) +#define root_pgentry_to_pfn(_x) (l4_pgentry_to_pfn(_x)) /* Pagetable walking. */ #define l2_pgentry_to_l1(_x) \ @@ -78,4 +82,13 @@ typedef l4_pgentry_t root_pgentry_t; /* Given a virtual address, get an entry offset into a linear page table. */ #define l1_linear_offset(_a) (((_a) & VADDR_MASK) >> PAGE_SHIFT) +#define PGT_root_page_table PGT_l4_page_table + +#define _PAGE_NX (cpu_has_nx ? (1UL<<63) : 0UL) + +#define L1_DISALLOW_MASK ((cpu_has_nx?0:(1UL<<63)) | (3UL << 7)) +#define L2_DISALLOW_MASK ((cpu_has_nx?0:(1UL<<63)) | (7UL << 7)) +#define L3_DISALLOW_MASK ((cpu_has_nx?0:(1UL<<63)) | (7UL << 7)) +#define L4_DISALLOW_MASK ((cpu_has_nx?0:(1UL<<63)) | (7UL << 7)) + #endif /* __X86_64_PAGE_H__ */ -- 2.30.2